-- woo lua!

require("vector.lua")
require("camera.lua")
require("fish.lua")
require("octopus.lua")
require("sprite.lua")
require("tentacle.lua")
require("tiles.lua")
require("utilities.lua")
require("particles.lua")
require("audio.lua")

bug = "yes"

-- run the physics engine at a fixed timestep of 60 Hz
local physics_timestep = 1.0 / 60.0

function love.load()
	-- filesystem setup
	love.filesystem.setIdentity("octopuslove")
	--bug = recursiveEnumerate("sprites/Fish_02", "")
	
	-- title screen
	title_screen = love.graphics.newImage("images/Title.jpg")
	instr_screen = love.graphics.newImage("images/Control.jpg")
	over_screen = love.graphics.newImage("images/GameOver.jpg")
	show_title = true
	
	-- font setup
	font = love.graphics.newImageFont("bluefont-1x.png", " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&`'*#=[]\"")
	font2 = love.graphics.newImageFont("bluefont-2x.png", " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&`'*#=[]\"")
	love.graphics.setFont(font);

	-- graphics setup
	love.graphics.setBackgroundColor(200, 255, 255)

	-- tile setup
	tileset[tile_id["gravel"]] = make_tiles("tiles/Grav_01")
	tileset[tile_id["rocks"]] = make_tiles("tiles/Stone_01")
	tileset[tile_id["sand"]] = make_tiles("tiles/Sand_00")
	tileset[tile_id["coral_g"]] = make_tiles("tiles/CoraG_01")
	tileset[tile_id["coral_p"]] = make_tiles("tiles/CoraP_02")
	tileset[tile_id["coral_r"]] = make_tiles("tiles/CoraR_03")
	tileset[tile_id["border"]] = make_tiles("tiles/Border_01")
--	tile_world:test()
	tile_world:load("world.txt")
	tile_world:fill_blends()

	-- sprite setup
	local sprites = love.filesystem.enumerate("sprites")
	for i, v in ipairs(sprites) do
		sprite:init("sprites/" .. v) -- load all sprites
	end

	-- selectively reverse some sprite's playback
	sprite_table["Fish_02"].playreverse = true

--	pb = playback:init(sprite_table["Fish_02"])

	-- octopus setup
	octopus:setupGraphics()

	-- camera setup
	setCamera(camera.stretchToResolution(1200,900)) -- 1200 x 900 units (roughly 12 x 9 meters in physics units)
	getCamera():setScreenOrigin(0.5, 0.5) -- left, bottom
	getCamera():scaleBy(1, -1) -- flip the y axis
	getCamera():pinInitial() -- capture initial settings
	
	getCamera().scale_target = 0.4
	getCamera().scale_val = 0.4
	
	-- swap out cameras for title screen (restored on first mouseup)
	game_cam = getCamera()
	screen_cam = camera.new()
	setCamera(screen_cam)

	-- input setup
	love.mouse.setGrab(false) -- let the mouse location leave the window
	mx, my = 0, 0

	-- physics setup
	world = love.physics.newWorld(100000, 100000) -- the physics world, hopefully used very little
    world:setCallbacks( collision_add, collision_persist, collision_remove, collision_result )

	-- world representation setup
	obj = {} -- all objects that the game keeps track of
    objects_to_destroy = {}

    octopus:init( world, 20000, -15000 )
--	table.insert(obj, octopus) -- put Mr. Octopus in to start with (broke this out to preserve draw order)

	cpos = octopus:getPos()

	physics_accumulator = 0

    -- water overlays
    overlay1 = love.graphics.newImage( "images/wateroverlay2.png" )

	-- entity setup
	for i = 1, 120 do
		table.insert(obj, fish:init("prey", math.random(0, 40000),   math.random(-14000, 0)))

	end
	for i = 1, 25 do
		table.insert(obj, fish:init("shark", math.random(0, 40000),   math.random(-14000, 0)))

	end
	for i = 1, 60 do
		table.insert(obj, fish:init("crab", math.random(0, 40000),   math.random(-14000, 0)))

	end
end

function love.keypressed(key)
	if key == 'r' then
		octopus.rocket = true
	end
end

function love.keyreleased(key)
	if key == 'escape' or key == 'q' then
		love.event.push('q') -- quit the game
	end
		
	if show_title or game_over then
		return
	end
		
	if key == 'r' then
		octopus.rocket = false
--	elseif key == ' ' then
--		octopus:toggle()
    elseif key == 'd' then
       octopus:damage()
    elseif key == 'p' then
       octopus:addScore(1500)
	end
end

function love.mousepressed(x, y, button)
	if show_title or game_over then
		return
	end

	if button == 'l' then
		octopus.charge_lunge = 0
	elseif button == 'r' then
		if octopus.mode == "speed" then
			octopus:toggle()
		end
		octopus.camo_sample_timer = 0
		
	elseif button == 'wu' then
	  	getCamera().scale_target = getCamera().scale_target * 1.1
	elseif button == 'wd' then
	  	getCamera().scale_target = getCamera().scale_target / 1.1
	end
end

function love.mousereleased(x, y, button)
	if show_title then
		if not show_title_2 then
			show_title_2 = true
		else
			setCamera(game_cam)
			show_title = false
		end
	end
	
	if game_over then
		return
	end

	if button == 'l' then
		octopus:lunge()
		octopus.decel = 4
	elseif button == 'r' then
		if octopus.camo_sample_timer >= 0 then
			octopus.camo_sample_timer = -1
		end
	end
end


function love.update(dt)
	if show_title or game_over then
		return
	end

	mx, my = love.mouse.getPosition()
	octopus:setTarget(mx, my)

	physics_accumulator = physics_accumulator + dt

	while physics_accumulator >= dt do
	   -- XXX: save previous physics state
	   world:update( physics_timestep )
	   physics_accumulator = physics_accumulator - dt
	end

	-- camera voodoo
	local carrot
	if octopus.mode == "speed" then
		carrot = 1000
	else
		carrot = 700
	end
	local ctarg = octopus:getPos() + carrot * vec2:dir(octopus.ang)
	if octopus.big_lunge < 0 then
		cpos = cpos + 4 * dt * (ctarg - cpos)
	end
	getCamera():bumpToFit(cpos.x, cpos.y, 0.4)
	
--	pb:update(dt)

	-- prep table for object deletion
	local rm = {}

	-- do update
	for i, v in ipairs(obj) do
		v:update(dt)
	if v.todelete then
			table.insert(rm, i)
		end
	end
	
	-- cleanup deleted objects
	table.sort(rm, function (a, b) return (b < a) end) -- reverse order to avoid stomping indices
	for i,v in ipairs(rm) do
		table.remove(obj, rm[i])
	end
	
	octopus:update(dt)
	
	getCamera():smoothScale(dt)
end

function love.draw()
	if show_title then
		setCamera(screen_cam)
		if show_title_2 then
			-- instructions screen here
			love.graphics.draw(instr_screen, 0, 0, 0, 1, 1)
		else
			love.graphics.draw(title_screen, 0, 0, 0, 1, 1)
		end
		setCamera(game_cam)
		return
     end
	
	if game_over then
		setCamera(screen_cam)
		love.graphics.draw(over_screen, 0, 0, 0, 1, 1)
		return
	end

	tile_world:draw()

	for i,v in ipairs(obj) do
		v:draw()
	end

	love.graphics.setColor(255, 255, 255)
--	pb:draw(octopus.pos + vec2:init(500, 500), octopus.ang, 2)
	
	octopus:draw() -- always want octopus to draw on top
	
     setCamera( screen_cam )
     love.graphics.setColor( 0, 40, 255, 100 )
     love.graphics.draw( overlay1, 0, love.graphics.getHeight(), 0, 1, -1 )
     setCamera( game_cam )

	-- score rendering
	love.graphics.setColor(255, 0, 0)
	love.graphics.setFont(font2)
	love.graphics.print("SCORE: " .. tostring(octopus.score), 15, 15)

	-- debug rendering
	love.graphics.setColor(255, 255, 255)
	tx, ty = getCamera():pos(mx, my)
	bug = tostring(vec2:init(math.floor(mx), math.floor(my)))
	love.graphics.setFont(font)
	love.graphics.print(bug, tx, ty); ty = ty + 10
	--love.graphics.print(tostring(octopus.pos), tx, ty); ty = ty + 10
	--love.graphics.print(tostring(octopus.vel), tx, ty); ty = ty + 10
end

camera.lateInit()
